﻿using System;
using System.Text;

namespace USArray
{

    public static class StringToolNoGC
    {
        //Copy
        public unsafe static void Unsafe_CopyFrom(this ref StringNoGC gthis, char* srcptr, int strlen)
        {
            if (srcptr == null || srcptr == gthis.HeadPtr || strlen == 0)
                return;

            if (gthis.MaxLength < strlen)
                throw new Exception("no enough space.");

            gthis.HeadPtr->length = strlen;
            char* dest = gthis.CharPtr;
            UnsafePtrTool.MemCpy(dest, srcptr, strlen * 2);

        }
        //正序查询
        public unsafe static int Unsafe_IndexOf(this ref StringNoGC gthis, char* srcptr, int strlen)
        {
            if (srcptr == null || strlen == 0 || strlen > gthis.Length)
                return -1;

            if (srcptr == gthis.HeadPtr) return 0;

            char* gthisptr = gthis.CharPtr;

            for (var i = 0; i <= gthis.Length - strlen; i++)
            {
                bool match = true;
                for (var si = 0; si < strlen; si++)
                {
                    if (gthisptr[si + i] != srcptr[si])
                    {
                        match = false; break;
                    }

                }
                if (match)
                    return i;
            }
            return -1;
        }
        //倒序查询
        public unsafe static int Unsafe_LastIndexOf(this ref StringNoGC gthis, char* srcptr, int strlen)
        {
            if (srcptr == null || strlen == 0 || strlen > gthis.Length)
                return -1;

            if (srcptr == gthis.HeadPtr) return 0;

            char* gthisptr = gthis.CharPtr;

            for (var i = gthis.Length - strlen; i >= 0; i--)
            {
                bool match = true;
                for (var si = 0; si < strlen; si++)
                {
                    if (gthisptr[si + i] != srcptr[si])
                    {
                        match = false; break;
                    }
                }
                if (match)
                    return i;
            }
            return -1;
        }
        //链接
        public unsafe static void Unsafe_Concat(this ref StringNoGC gthis, char* srcptr, int strlen)
        {
            if (strlen + gthis.Length > gthis.MaxLength)
                throw new Exception("not enought space.");
            char* gthisptr = gthis.CharPtr;

            var srclen = gthis.Length;
            for (var i = 0; i < strlen; i++)
            {
                gthisptr[i + srclen] = srcptr[i];
            }
            gthis.HeadPtr->length = srclen + strlen;
        }
        //交换
        public unsafe static void Unsafe_Replace(this ref StringNoGC gthis, int index, int len, char* repstr, int repstrlen)
        {
            var newlen = gthis.Length - len + repstrlen;
            if (newlen > gthis.MaxLength)
                throw new Exception("not enought space.");


            char* gthisptr = gthis.CharPtr;

            int movestart = index + len;
            int movelen = gthis.Length - movestart;

            int moveto = index + repstrlen;
            if (moveto > movestart)
            {//右移动
                for (var i = movelen - 1; i >= 0; i--)
                {
                    gthisptr[moveto + i] = gthisptr[movestart + i];
                }
            }
            else if (moveto < movestart)
            {//左移动
                for (var i = 0; i < movelen; i++)
                {
                    gthisptr[moveto + i] = gthisptr[movestart + i];
                }
            }
            //替换
            for (var i = 0; i < repstrlen; i++)
            {
                gthisptr[index + i] = repstr[i];
            }

            gthis.HeadPtr->length = newlen;
        }


        //取子串
        public static void SubString(this ref StringNoGC gthis, ref StringNoGC outgc, int index, int len = -1)
        {
            if (index < 0 || index > gthis.Length)
                throw new IndexOutOfRangeException();

            if (len < 0)
                len = gthis.Length - index;


            if (outgc.MaxLength < len)
                throw new Exception("not enough space.");

            if (index + len > gthis.Length)
                throw new Exception("sub string range is too much");
            unsafe
            {
                char* ptr = gthis.CharPtr + index;
                char* outptr = outgc.CharPtr;
                for (var i = 0; i < len; i++)
                {
                    outptr[i] = ptr[i];
                }
                outgc.HeadPtr->length = len;
            }
        }
        //删除
        public static void Remove(this ref StringNoGC gthis, int index, int len)
        {
            unsafe
            {
                var glen = gthis.Length;
                if (index + len > glen)
                    throw new Exception("remove too much");
                if (len == 0) return;

                char* gthisptr = gthis.CharPtr;

                int movestart = index + len;
                int movelen = gthis.Length - movestart;

                int moveto = index;
                //左移
                for (var i = 0; i < movelen; i++)
                {
                    gthisptr[moveto + i] = gthisptr[movestart + i];
                }
                gthis.HeadPtr->length = glen - len;
            }
        }

        //从串Copy

        public static void CopyFrom(this ref StringNoGC gthis, string sysstr)
        {
            unsafe
            {
                fixed (char* srcptr = sysstr)
                {
                    Unsafe_CopyFrom(ref gthis, srcptr, sysstr.Length);
                }
            }
        }
        public static void CopyFrom(this ref StringNoGC gthis, ref StringNoGC nogc)
        {
            unsafe
            {
                Unsafe_CopyFrom(ref gthis, nogc.CharPtr, nogc.Length);
            }
        }

        //查询
        public static int IndexOf(this ref StringNoGC gthis, string sysstr)
        {
            unsafe
            {
                fixed (char* srcptr = sysstr)
                {
                    return Unsafe_IndexOf(ref gthis, srcptr, sysstr.Length);
                }
            }
        }
        public static int IndexOf(this ref StringNoGC gthis, ref StringNoGC nogc)
        {
            unsafe
            {
                return Unsafe_IndexOf(ref gthis, nogc.CharPtr, nogc.Length);
            }
        }

        //倒序查询
        public static int LastIndexOf(this ref StringNoGC gthis, string sysstr)
        {
            unsafe
            {
                fixed (char* srcptr = sysstr)
                {
                    return Unsafe_LastIndexOf(ref gthis, srcptr, sysstr.Length);
                }
            }
        }
        public static int LastIndexOf(this ref StringNoGC gthis, ref StringNoGC nogc)
        {
            unsafe
            {
                return Unsafe_LastIndexOf(ref gthis, nogc.CharPtr, nogc.Length);
            }
        }

        //连接字符串
        public static void Concat(this ref StringNoGC gthis, string sysstr)
        {
            unsafe
            {
                fixed (char* srcptr = sysstr)
                {
                    Unsafe_Concat(ref gthis, srcptr, sysstr.Length);
                }
            }
        }
        public static void Concat(this ref StringNoGC gthis, ref StringNoGC nogc)
        {
            unsafe
            {
                Unsafe_Concat(ref gthis, nogc.CharPtr, nogc.Length);
            }
        }
        public static void ConcatStringBuilder(this ref StringNoGC gthis, StringBuilder sb)
        {
            unsafe
            {
                var strlen = sb.Length;
                if (strlen + gthis.Length > gthis.MaxLength)
                    throw new Exception("not enought space.");
                char* gthisptr = (char*)(gthis.HeadPtr + 1);

                var srclen = gthis.Length;
                for (var i = 0; i < strlen; i++)
                {
                    gthisptr[i + srclen] = sb[i];
                }
                gthis.HeadPtr->length = srclen + strlen;

            }
        }

        //删除
        public static void Remove(this ref StringNoGC gthis, string str)
        {
            var i = gthis.IndexOf(str);
            if (i < 0)
                return;
            gthis.Remove(i, str.Length);
        }
        public static void Remove(this ref StringNoGC gthis, ref StringNoGC str)
        {
            var i = gthis.IndexOf(ref str);
            if (i < 0)
                return;
            gthis.Remove(i, str.Length);
        }

        //替换字符串
        public static void Replace(this ref StringNoGC gthis, int srcindex, int srclen, string str)
        {
            unsafe
            {
                fixed (char* srcptr = str)
                {
                    Unsafe_Replace(ref gthis, srcindex, srclen, srcptr, str.Length);
                }
            }
        }
        public static void Replace(this ref StringNoGC gthis, int srcindex, int srclen, ref StringNoGC nogc)
        {
            unsafe
            {
                Unsafe_Replace(ref gthis, srcindex, srclen, nogc.CharPtr, nogc.Length);
            }
        }


        public static void Replace(this ref StringNoGC gthis, string str1, string str2)
        {
            var i = gthis.IndexOf(str1);
            if (i < 0)
                return;
            gthis.Replace(i, str1.Length, str2);
        }
        public static void Replace(this ref StringNoGC gthis, ref StringNoGC str1, ref StringNoGC str2)
        {
            var i = gthis.IndexOf(ref str1);
            if (i < 0)
                return;
            gthis.Replace(i, str1.Length, ref str2);
        }

    }
}
